package sg.edu.nus.iss.billing.gui.subscription;

import static sg.edu.nus.iss.billing.gui.subscription.UIConstants.TXT_H;
import static sg.edu.nus.iss.billing.gui.subscription.UIConstants.TXT_W;
import static sg.edu.nus.iss.billing.localization.MessageKeyManager.getMessage;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.swing.BorderFactory;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;

import sg.edu.nus.iss.billing.entity.service.RateChargable;
import sg.edu.nus.iss.billing.entity.service.Service;
import sg.edu.nus.iss.billing.exception.ValidationException;
import sg.edu.nus.iss.billing.gui.component.ValidateJTextField;
import sg.edu.nus.iss.billing.util.Util;
import sg.edu.nus.iss.billing.validation.ValidationRule;

public class ServiceViewPanel extends javax.swing.JPanel {

	private static final String IS_SUBSCRIBED = "true";

	private static final long serialVersionUID = 8619461737498502961L;

	private JScrollPane svcViewScrollPane;

	private JPanel svcPanel;

	private JLabel titles[] = new JLabel[8];
	
	private boolean isBasicSvc = false;
	
	private boolean isViewModel = false;
	
	private boolean isBasicSvcChoosable = false;

	private Map<String, String[]> origData = new HashMap<String, String[]>();
	
	private List<JComponent[]> contents = new ArrayList<JComponent[]>();

	
	public ServiceViewPanel() {
		super();
		initGUI();
	}

	/**
	 * Add service info row by row
	 * @param row from number 1
	 * @param data service info, 
	 * 		  The order is: serviceId, ServiceName, FixMonthFee,RateType,Rate, 
	 * 		  ServiceCommencedDate, ServicegTerminateDate, isSubscribed
	 */
	public void addRow(int row, Service svc, Date startDt, Date endDt, Boolean isRegistered) {
		
		String[] data = svc2Array(svc, startDt, endDt, isRegistered);
		Rectangle rec[] = getRectangle(row +1);
		JComponent comGrp[] = new JComponent[8];
		JTextField txt = null;
		for (int i = 0; i <7; i++) {
			if(i == 5){
				txt = new ValidateJTextField(getMessage("service.commencedDt"), ValidationRule.GREATER_THAN_TODAY);
			} else if( i == 6){
				txt = new ValidateJTextField(getMessage("service.terminateDt"), ValidationRule.GREATER_THAN_TODAY);
			} else {
				txt = new JTextField();
			}
			txt.setText(data[i]);
			txt.setEditable(false);
			txt.setBounds(rec[i]);
			txt.setBorder(BorderFactory.createTitledBorder(""));
			this.svcPanel.add(txt);
			comGrp[i] = txt;
		}
		JCheckBox chk = new JCheckBox();

		if (data[7] !=null &&data[7].equals(IS_SUBSCRIBED)) {
			chk.setSelected(true);
			//((JTextField) comGrp[6]).setEditable(true);
		}
		if (isBasicSvc) {
			((JTextField)comGrp[2]).setText("0.0");
			if(isBasicSvcChoosable) {
				chk.setEnabled(true);
				chk.addActionListener(new BasicSVCCheckBoxChangeListener());
			} else {
				chk.setSelected(true);
				chk.setEnabled(false);
			}
		} else {
			chk.addActionListener(new CheckBoxChangeListener());
		}
		if(isViewModel){
			chk.setEnabled(false);
		}
		// row number as the text
		chk.setText(String.valueOf(row));
		
		chk.setBounds(rec[7]);
		this.svcPanel.add(chk);
		comGrp[7] = chk;
		contents.add(comGrp);
		origData.put(data[0], data);
	}

	public void removeAllRow() {

		for (JComponent[] coms : contents) {
			for (JComponent com : coms) {
				this.svcPanel.remove(com);
			}
		}
		contents.clear();
		origData.clear();
		this.updateUI();
	}
	
	public void setIsViewModel(boolean isViewModel){
		this.isViewModel = isViewModel;
	}
	
	/**
	 * return the de-registered services
	 * @return
	 * 		 the order is service id, terminate date
	 */
	public List<String> getDeregisteredServices() {

		List<String> list = new ArrayList<String>();
		for (Component[] coms : contents) {
			if (! ((JCheckBox) coms[7]).isSelected()) {
				String id = ((JTextField) coms[0]).getText();
				if(origData.get(id)[7].equals(IS_SUBSCRIBED)){
					list.add(id);
				}
			}
		}
		return list;

	}

	/**
	 * 
	 * @return String[]
	 * 		  the new registered service ,order is: id, startDate,terminateDate
	 * @throws ValidationException 
	 */
	public List<String[]> getNewRegisteredServices() throws ValidationException {

		String services[];
		List<String[]> list = new ArrayList<String[]>();
		for (Component[] coms : contents) {
			if ( ((JCheckBox) coms[7]).isSelected()) {
				services = new String[3];
				String id = ((JTextField) coms[0]).getText();
				if (! origData.get(id)[7].equals(IS_SUBSCRIBED) || !isBasicSvcChoosable) {
					String startDt = ((ValidateJTextField) coms[5]).getValidatedText();
					String terminateDt = ((ValidateJTextField) coms[6]).getValidatedText();
					services[0] = id;
					services[1] = startDt;
					services[2] = terminateDt;
					list.add(services);
				}
			}
		}
		return list;

	}

	/**
	 *
	 * @return String[]
	 * 		  the service id and modified termination date,
	 *	      the order is: id, ServicegTerminateDate
	 * @throws ValidationException 
	 */
	public List<String[]> getModifiedRegisteredServices() throws ValidationException {

		String services[];
		List<String[]> list = new ArrayList<String[]>();
		for (Component[] coms : contents) {
			if ( ((JCheckBox) coms[7]).isSelected()) {
				services = new String[2];
				String id = ((JTextField) coms[0]).getText();
				String terminateDt = ((ValidateJTextField) coms[6]).getValidatedText();
				if (origData.get(id)[7].equals("true") && ! origData.get(id)[6].equals(terminateDt)) {
					services[0] = id;
					services[1] = terminateDt;
					list.add(services);
				}
			}
		}
		return list;

	}
	
	public int getSelectedCount(){
		int count = 0;
		for (Component[] coms : contents) {
			if ( ((JCheckBox) coms[7]).isSelected()) {
				count++;
			}
		}
		return count;
	}

	public void setIsBasicSvc(boolean isBasicSvc) {

		this.isBasicSvc = isBasicSvc;
	}
	
	public void setBasicChociable(boolean isBasicChociable) {
	
		this.isBasicSvcChoosable = isBasicChociable;
	}
	
	public void disableRow(String svcId){
		for (Component[] coms : contents) {
			if ( ((JTextField) coms[0]).getText().equals(svcId)) {
				for(Component c:coms){
					c.setEnabled(false);
					
				}
				break;
			}
		}
	}
	
	public void enableRow(String svcId){
		for (Component[] coms : contents) {
			if ( ((JTextField) coms[0]).getText().equals(svcId)) {
				for(Component c:coms){
					c.setEnabled(true);
					
				}
				break;
			}
		}
	}

	private void initGUI() {

		BorderLayout thisLayout = new BorderLayout();
		this.setLayout(thisLayout);
		setPreferredSize(new Dimension(UIConstants.CONTENT_W, 300));
		svcViewScrollPane = new JScrollPane();

		this.add(svcViewScrollPane, BorderLayout.CENTER);
		svcPanel = new JPanel();
		svcPanel.setLayout(null);
		svcViewScrollPane.setViewportView(svcPanel);
		svcPanel.setBorder(BorderFactory.createTitledBorder(""));
		svcPanel.setAutoscrolls(true);
		initTitle();
	}

	private Rectangle[] getRectangle(int row) {

		Rectangle rec[] = new Rectangle[8];
		int currentX = 1;
		int currentY = 0 + (row -1) * TXT_H;
		rec[0] = new Rectangle(currentX, currentY, 30, TXT_H);
		currentX += 30;
		rec[1] = new Rectangle(currentX, currentY, TXT_W, TXT_H);
		currentX += TXT_W;
		rec[2] = new Rectangle(currentX, currentY, 105, TXT_H);
		currentX += 105;
		rec[3] = new Rectangle(currentX, currentY, 80, TXT_H);
		currentX += 80;
		rec[4] = new Rectangle(currentX, currentY, 60, TXT_H);
		currentX += 60;
		rec[5] = new Rectangle(currentX, currentY, TXT_W-5, TXT_H);
		currentX += TXT_W-8;
		rec[6] = new Rectangle(currentX, currentY, TXT_W-5, TXT_H);
		currentX += TXT_W-8;
		rec[7] = new Rectangle(currentX, currentY, 25, TXT_H);
		return rec;
	}

	private void initTitle() {

		Rectangle rec[] = getRectangle(1);
		titles[0] = new JLabel(getMessage("service.id"));
		titles[1] = new JLabel(getMessage("service.name"));
		titles[2] = new JLabel(getMessage("service.fixMonthFee"));
		titles[3] = new JLabel(getMessage("service.rateType"));
		titles[4] = new JLabel(getMessage("service.rate"));
		titles[5] = new JLabel(getMessage("service.commencedDt"));
		titles[6] = new JLabel(getMessage("service.terminateDt"));
		titles[7] = new JLabel(getMessage("service.status"));
		for (int i = 0; i <titles.length; i++) {
			titles[i].setBounds(UIConstants.getXPosition(i +1), UIConstants.getYPosition(1), TXT_W, TXT_H);
			titles[i].setBounds(rec[i]);
			titles[i].setBorder(BorderFactory.createTitledBorder(""));
			this.svcPanel.add(titles[i]);
		}
	}

	private String[] svc2Array(Service svc, Date startDt, Date endDt, Boolean isRegistered) {
		
		String[] array = new String[8];
		array[0] = svc.getId();
		array[1] = svc.getServiceName();
		array[2] = svc.getFixedMonthlyCharge() ==null ? "" : String.valueOf(svc.getFixedMonthlyCharge());
		if(svc instanceof RateChargable){
			RateChargable rc = (RateChargable)svc;
			array[3] = rc.getRateUnit() ==null ? "" : String.valueOf(rc.getRateUnit());
			array[4] = rc.getServiceRate() ==null ? "" : String.valueOf(rc.getServiceRate());
		}else{
			array[3] = "";
			array[4] = "";
		}
		array[5] = startDt ==null ? "" : Util.getStringFromdate(startDt);
		array[6] = endDt ==null ? "" : Util.getStringFromdate(endDt);
		array[7] = isRegistered ==true ? IS_SUBSCRIBED : "false";

		return array;

	}

	private class CheckBoxChangeListener implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent e) {

			JCheckBox chk = (JCheckBox) e.getSource();
			int row = Integer.parseInt(chk.getText());
			JComponent[] coms = contents.get(row -1);
			String svcId = ((JTextField) coms[0]).getText();
			JTextField startDt = (JTextField) coms[5];
			JTextField endDt = (JTextField) coms[6];

			boolean isSubscribedBefore = false;
			if (origData.get(svcId)[7].equals(IS_SUBSCRIBED)) {
				isSubscribedBefore = true;
			}
			if (chk.isSelected()) {
				if (isSubscribedBefore) {
					startDt.setEditable(false);
					endDt.setEditable(false);
					endDt.setText(origData.get(svcId)[6]);
				} else {
					startDt.setEditable(true);
					startDt.setText(Util.getStringFromdate(new Date()));
					endDt.setEditable(true);
				}
			} else {
				startDt.setEditable(false);
				endDt.setEditable(false);
				if (! isSubscribedBefore) {
					startDt.setText("");
					endDt.setText("");
				} else {
					endDt.setText(Util.getStringFromdate(new Date()));
				}
			}
			
			
			
		}
	}
	
	private class BasicSVCCheckBoxChangeListener implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent e) {

			JCheckBox chk = (JCheckBox) e.getSource();
			int row = Integer.parseInt(chk.getText());
			JComponent[] coms = contents.get(row -1);
			String svcId = ((JTextField) coms[0]).getText();
			JTextField startDt = (JTextField) coms[5];
			JTextField endDt = (JTextField) coms[6];

			boolean isSubscribedBefore = false;
			if (origData.get(svcId)[7].equals(IS_SUBSCRIBED)) {
				isSubscribedBefore = true;
			}
			if (chk.isSelected()) {
				if (isSubscribedBefore) {
					startDt.setText(origData.get(svcId)[5]);
					endDt.setText(origData.get(svcId)[6]);
				} else {
					startDt.setText(Util.getStringFromdate(new Date()));
				}
			} else {
				if (! isSubscribedBefore) {
					startDt.setText("");
					endDt.setText("");
				} else {
					endDt.setText(Util.getStringFromdate(new Date()));
				}
			}
		}
	}

}
